From 803e13b32cf0ff8b496649fb0a4d6e32400e98a4 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 14 Jul 2021 22:23:40 +0200 Subject: feat(ui): Migrate to PatternFly 4 design framework This change is a rewrite of the existing OpenDC frontend in order to migrate to the PatternFly 4 design framework. PatternFly is used by Red Hat for various computing related services such as OpenShift, Red Hat Virtualization and Cockpit. Since their design requirements are very similar to those of OpenDC (modeling computing services), migrating to PatternFly 4 allows us to re-use design choices from these services. See https://www.patternfly.org/v4/ for more information about PatternFly. --- .../src/pages/projects/[project]/index.js | 111 +++++++++++++- .../projects/[project]/portfolios/[portfolio].js | 170 ++++++++++++++++++--- .../projects/[project]/topologies/[topology].js | 73 ++++++--- 3 files changed, 310 insertions(+), 44 deletions(-) (limited to 'opendc-web/opendc-web-ui/src/pages/projects/[project]') diff --git a/opendc-web/opendc-web-ui/src/pages/projects/[project]/index.js b/opendc-web/opendc-web-ui/src/pages/projects/[project]/index.js index cce887aa..c6ded12b 100644 --- a/opendc-web/opendc-web-ui/src/pages/projects/[project]/index.js +++ b/opendc-web/opendc-web-ui/src/pages/projects/[project]/index.js @@ -20,6 +20,113 @@ * SOFTWARE. */ -import Topology from './topologies/[topology]' +import { useRouter } from 'next/router' +import { useProject } from '../../../data/project' +import { AppPage } from '../../../components/AppPage' +import Head from 'next/head' +import { + Breadcrumb, + BreadcrumbItem, + Button, + Card, + CardActions, + CardBody, + CardHeader, + CardTitle, + DescriptionList, + DescriptionListDescription, + DescriptionListGroup, + DescriptionListTerm, + Grid, + GridItem, + PageSection, + PageSectionVariants, + Skeleton, + Text, + TextContent, +} from '@patternfly/react-core' +import BreadcrumbLink from '../../../components/util/BreadcrumbLink' +import PortfolioTable from '../../../components/projects/PortfolioTable' +import TopologyTable from '../../../components/projects/TopologyTable' +import NewTopology from '../../../components/projects/NewTopology' +import NewPortfolio from '../../../components/projects/NewPortfolio' -export default Topology +function Project() { + const router = useRouter() + const { project: projectId } = router.query + + const { data: project } = useProject(projectId) + + const breadcrumb = ( + + + Projects + + + Project details + + + ) + + return ( + + + {project?.name ?? 'Project'} - OpenDC + + + + + {project?.name ?? } + + + + + + + + Details + + + + Name + + {project?.name ?? } + + + + + + + + + + + + + Topologies + + + + + + + + + + + + + Portfolios + + + + + + + + + + ) +} + +export default Project diff --git a/opendc-web/opendc-web-ui/src/pages/projects/[project]/portfolios/[portfolio].js b/opendc-web/opendc-web-ui/src/pages/projects/[project]/portfolios/[portfolio].js index d3d61271..55bee445 100644 --- a/opendc-web/opendc-web-ui/src/pages/projects/[project]/portfolios/[portfolio].js +++ b/opendc-web/opendc-web-ui/src/pages/projects/[project]/portfolios/[portfolio].js @@ -22,12 +22,41 @@ import { useRouter } from 'next/router' import Head from 'next/head' -import AppNavbarContainer from '../../../../containers/navigation/AppNavbarContainer' -import React from 'react' -import { useProject } from '../../../../data/project' -import ProjectSidebarContainer from '../../../../containers/app/sidebars/project/ProjectSidebarContainer' -import PortfolioResultsContainer from '../../../../containers/app/results/PortfolioResultsContainer' -import { useDispatch } from 'react-redux' +import React, { useRef } from 'react' +import { usePortfolio, useProject } from '../../../../data/project' +import { + Breadcrumb, + BreadcrumbItem, + Card, + CardActions, + CardBody, + CardHeader, + CardTitle, + Chip, + ChipGroup, + DescriptionList, + DescriptionListDescription, + DescriptionListGroup, + DescriptionListTerm, + Divider, + Grid, + GridItem, + PageSection, + PageSectionVariants, + Skeleton, + Tab, + TabContent, + Tabs, + TabTitleText, + Text, + TextContent, +} from '@patternfly/react-core' +import { AppPage } from '../../../../components/AppPage' +import BreadcrumbLink from '../../../../components/util/BreadcrumbLink' +import ScenarioTable from '../../../../components/projects/ScenarioTable' +import NewScenario from '../../../../components/projects/NewScenario' +import { METRIC_NAMES } from '../../../../util/available-metrics' +import PortfolioResults from '../../../../components/app/results/PortfolioResults' /** * Page that displays the results in a portfolio. @@ -36,24 +65,127 @@ function Portfolio() { const router = useRouter() const { project: projectId, portfolio: portfolioId } = router.query - const project = useProject(projectId) - const title = project?.name ? project?.name + ' - OpenDC' : 'Simulation - OpenDC' + const { data: project } = useProject(projectId) + const { data: portfolio } = usePortfolio(portfolioId) - const dispatch = useDispatch() + const overviewRef = useRef(null) + const resultsRef = useRef(null) + + const breadcrumb = ( + + + Projects + + + Project details + + + Portfolio + + + ) return ( -
+ - {title} + {project?.name ?? 'Portfolios'} - OpenDC - -
- -
- -
-
-
+ + + Portfolio + + + + + + Overview} + tabContentId="overview" + tabContentRef={overviewRef} + /> + Results} + tabContentId="results" + tabContentRef={resultsRef} + /> + + + + + + + + Details + + + + Name + + {portfolio?.name ?? } + + + + Scenarios + + {portfolio?.scenarioIds.length ?? ( + + )} + + + + Metrics + + {portfolio?.targets?.enabledMetrics ? ( + portfolio.targets.enabledMetrics.length > 0 ? ( + + {portfolio.targets.enabledMetrics.map((metric) => ( + + {METRIC_NAMES[metric]} + + ))} + + ) : ( + 'No metrics enabled' + ) + ) : ( + + )} + + + + Repeats per Scenario + + {portfolio?.targets?.repeatsPerScenario ?? ( + + )} + + + + + + + + + + + + + Scenarios + + + + + + + + + + + ) } diff --git a/opendc-web/opendc-web-ui/src/pages/projects/[project]/topologies/[topology].js b/opendc-web/opendc-web-ui/src/pages/projects/[project]/topologies/[topology].js index a9dfdb19..5873ed11 100644 --- a/opendc-web/opendc-web-ui/src/pages/projects/[project]/topologies/[topology].js +++ b/opendc-web/opendc-web-ui/src/pages/projects/[project]/topologies/[topology].js @@ -23,18 +23,29 @@ import { useRouter } from 'next/router' import { useProject } from '../../../../data/project' import { useDispatch, useSelector } from 'react-redux' -import React, { useEffect } from 'react' +import React, { useEffect, useState } from 'react' import { HotKeys } from 'react-hotkeys' import { KeymapConfiguration } from '../../../../hotkeys' import Head from 'next/head' -import AppNavbarContainer from '../../../../containers/navigation/AppNavbarContainer' -import LoadingScreen from '../../../../components/app/map/LoadingScreen' -import MapStage from '../../../../containers/app/map/MapStage' -import ScaleIndicatorContainer from '../../../../containers/app/map/controls/ScaleIndicatorContainer' -import ToolPanelComponent from '../../../../components/app/map/controls/ToolPanelComponent' -import ProjectSidebarContainer from '../../../../containers/app/sidebars/project/ProjectSidebarContainer' -import TopologySidebarContainer from '../../../../containers/app/sidebars/topology/TopologySidebarContainer' +import MapStage from '../../../../components/app/map/MapStage' import { openProjectSucceeded } from '../../../../redux/actions/projects' +import { AppPage } from '../../../../components/AppPage' +import { + Bullseye, + Drawer, + DrawerContent, + DrawerContentBody, + EmptyState, + EmptyStateIcon, + Spinner, + Title, +} from '@patternfly/react-core' +import { zoomInOnCenter } from '../../../../redux/actions/map' +import Toolbar from '../../../../components/app/map/controls/Toolbar' +import { useMapScale } from '../../../../data/map' +import ScaleIndicator from '../../../../components/app/map/controls/ScaleIndicator' +import TopologySidebar from '../../../../components/app/sidebars/topology/TopologySidebar' +import Collapse from '../../../../components/app/map/controls/Collapse' /** * Page that displays a datacenter topology. @@ -44,7 +55,6 @@ function Topology() { const { project: projectId, topology: topologyId } = router.query const { data: project } = useProject(projectId) - const title = project?.name ? project?.name + ' - OpenDC' : 'Simulation - OpenDC' const dispatch = useDispatch() useEffect(() => { @@ -54,27 +64,44 @@ function Topology() { }, [projectId, topologyId, dispatch]) const topologyIsLoading = useSelector((state) => state.currentTopologyId === '-1') + const scale = useMapScale() + const interactionLevel = useSelector((state) => state.interactionLevel) + + const [isExpanded, setExpanded] = useState(true) + const panelContent = setExpanded(false)} /> return ( - + - {title} + {project?.name ?? 'Topologies'} - OpenDC - {topologyIsLoading ? ( -
- -
+ + + + + Loading Topology + + + ) : ( -
- - - - - -
+ + + + + + + dispatch(zoomInOnCenter(zoomIn))} + onExport={() => window['exportCanvasToImage']()} + /> + setExpanded(true)} /> + + + + )} -
+ ) } -- cgit v1.2.3